<template>
  <div class="menu-container">
    <div class="my-row">
      <el-table
        ref="menuTabTree"
        row-key="uid"
        highlight-current-row
        border
        lazy
        :data="menuList"
        @row-dblclick="tabDBClick"
        :load="loadMenus">
        <el-table-column
          prop="code"
          :label="$t('menu.code')"
          width="200">
        </el-table-column>
        <el-table-column
          prop="name"
          :label="$t('menu.name')"
          width="160">
        </el-table-column>
        <el-table-column
          prop="localeEn"
          :label="$t('menu.localeEn')"
          width="160">
        </el-table-column>
        <el-table-column
          prop="path"
          :label="$t('menu.path')"
          width="180">
        </el-table-column>
        <el-table-column
          prop="component"
          :label="$t('menu.component')"
          width="180">
        </el-table-column>
        <el-table-column
          prop="sort"
          :label="$t('menu.sort')"
          min-width="80"
        >
        </el-table-column>
        <el-table-column
          fixed="right"
          :label="$t('common.opt')"
          width="150">
          <template slot-scope="scope">
            <el-link v-if="isAdd" @click="add(scope.row.uid)" type="primary">{{$t('common.add')}}</el-link>
            <el-link v-if="isEdit" @click="edit(scope.row.uid)" type="warning">{{$t('common.edit')}}</el-link>
            <el-link v-if="isDel" @click="delMenu(scope.row)" type="danger">{{$t('common.del')}}</el-link>
          </template>
        </el-table-column>
      </el-table>
      <el-button v-if="isAdd" @click="add('')" size="mini" icon="el-icon-plus"
                 style="margin-top: 10px; width: 100%;"></el-button>
    </div>

    <el-dialog v-if="isAdd || isEdit"
               :title="title"
               :visible.sync="dialogShow"
               width="300"
               @open="onOpen"
               @close="onClose">
      <span>
        <el-form :disabled="isDisabled" ref="form" :model="form" :rules="rules" label-width="120px">
          <el-form-item :label="$t('menu.name')" prop="name">
            <el-input v-model="form.name"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.localeEn')" prop="localeEn">
            <el-input v-model="form.localeEn"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.path')">
            <el-input v-model="form.path"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.component')">
            <el-input v-model="form.component"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.icon')">
            <el-input v-model="form.icon"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.logo')">
            <el-input v-model="form.logo"></el-input>
          </el-form-item>
          <el-form-item :label="$t('menu.sort')">
            <el-input v-model="form.sort"></el-input>
          </el-form-item>
        </el-form>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" icon="el-icon-check" :loading="saveLoading" @click="onSubmit">
          {{$t('common.save')}}
        </el-button>
        <el-button icon="el-icon-close" :disabled="saveLoading" @click="dialogShow = false;">
          {{$t('common.cancel')}}
        </el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  import {list, get, add, edit, del} from '@/api/menu/index';

  export default {
    name: 'Menu',
    data() {
      return {
        isAdd: true,
        isEdit: true,
        isDel: true,
        isDisabled: true,
        dialogShow: false,
        saveLoading: false,
        submitType: '',
        title: '',
        menuList: [],
        form: {
          name: '',
          code: '',
          parentCode: '',
          localeEn: '',
          icon: '',
          path: '',
          component: '',
          logo: '',
          sort: ''
        }
      }
    },
    computed: {
      rules() {
        return {
          name: [
            {required: true, message: this.$t('menu.rules.nameRequired'), trigger: 'blur'},
            {min: 1, max: 100, message: this.$t('menu.rules.lengthMsg'), trigger: 'blur'}
          ],
          localeEn: [
            {required: true, message: this.$t('menu.rules.localeEnRequired'), trigger: 'blur'},
            {min: 1, max: 100, message: this.$t('menu.rules.lengthMsg'), trigger: 'blur'}
          ]
        };
      }
    },
    mounted() {
      list('0').then(data => {
        for (let i = 0, l = data.length; i < l; i++) {
          data[i]['hasChildren'] = true;
        }
        this.menuList = data;
      })
    },
    methods: {
      loadMenus(tree, treeNode, resolve) {
        list(tree.uid).then(data => {
          for (let i = 0, l = data.length; i < l; i++) {
            data[i]['hasChildren'] = true;
          }
          resolve(data);
        });
      },
      tabDBClick(row, column, event) {
        this.$refs.menuTabTree.store.loadOrToggle(row);
      },
      add(parentCode) {
        this.title = this.$t('common.add');
        this.form.parentCode = parentCode;
        this.submitType = 'add';
        this.dialogShow = true;
      },
      edit(uid) {
        this.title = this.$t('common.edit');
        this.submitType = 'edit';
        this.dialogShow = true;
        get(uid).then(res => {
          this.form = res.data;
        });
      },
      onSubmit() {
        this.$refs.form.validate(valid => {
          if (valid) {
            this.saveLoading = true;
            if (this.submitType == 'add') {
              add(this.form).then(res => {
                this.saveLoading = false;
                this.dialogShow = false;
                res.data.hasChildren = true;
                this.refreshData(res.data, 'add');
                this.$message({
                  type: 'success',
                  message: this.$t('common.success')
                });
              }).catch(() => {
                this.saveLoading = false;
              });
            } else if (this.submitType == 'edit') {
              if (this.form.uid == '') {
                this.$message.error(this.$t('common.noSelected'));
                return;
              }
              edit(this.form).then(() => {
                this.saveLoading = false;
                this.dialogShow = false;
                this.form.hasChildren = true;
                this.refreshData(JSON.parse(JSON.stringify(this.form)), 'edit');
                this.form = {};
                this.$message({
                  type: 'success',
                  message: this.$t('common.success')
                });
              }).catch(() => {
                this.saveLoading = false;
              });
            }

          }
        });
      },
      refreshData(row, type) {
        if (row.parentCode == '0') {
          if (type == 'add') {
            this.menuList.push(row);
          } else if (type == 'edit') {
            for (let i = 0, l = this.menuList.length; i < l; i++) {
              if (this.menuList[i].uid == row.uid) {
                this.menuList.splice(i, 1, row);
                break;
              }
            }
          }
        } else {
          let children = this.$refs.menuTabTree.store.states.lazyTreeNodeMap[row.parentCode];
          if (children) {
            if (type == 'add') {
              children.push(row);
            } else if (type == 'edit') {
              for (let i = 0, l = children.length; i < l; i++) {
                if (children[i].uid == row.uid) {
                  children.splice(i, 1, row);
                  break;
                }
              }
            }
            this.$set(this.$refs.menuTabTree.store.states.lazyTreeNodeMap, row.parentCode, children);
          } else {
            this.$refs.menuTabTree.store.loadOrToggle({uid: row.parentCode});
          }
        }
      },
      delMenu(row) {
        this.$confirm(this.$t('common.delMsg'), this.$t('common.del'), {
          confirmButtonText: this.$t('common.done'),
          cancelButtonText: this.$t('common.cancel'),
          type: 'warning',
          confirmButtonClass: 'el-icon-delete',
          cancelButtonClass: 'el-icon-close',
          beforeClose: (action, instance, done) => {
            if (action === 'confirm') {
              instance.confirmButtonLoading = true;
              del(row.code).then(() => {
                done();
                instance.confirmButtonLoading = false;
                if (row.parentCode == '0') {
                  for (let i = 0, l = this.menuList.length; i < l; i++) {
                    if (this.menuList[i].uid == row.uid) {
                      this.$delete(this.menuList, i);
                      break;
                    }
                  }
                } else {
                  let children = this.$refs.menuTabTree.store.states.lazyTreeNodeMap[row.parentCode];
                  for (let i = 0, l = children.length; i < l; i++) {
                    if (children[i]['uid'] == row.uid) {
                      this.$delete(children, i);
                      break;
                    }
                  }
                  this.$set(this.$refs.menuTabTree.store.states.lazyTreeNodeMap, row.parentCode, children);
                }
                this.$message({
                  type: 'success',
                  message: this.$t('common.success')
                });
              });
            } else {
              done();
            }
          }
        });
      },
      onOpen() {
        this.isDisabled = false;
        if (this.$refs.form !== undefined) {
          this.$refs.form.resetFields();
          this.form.sort = '';// 特殊处理，resetFields重置不了sort，其它字段都能重置，不知什么原因
        }
      },
      onClose() {
        this.isDisabled = true;
      }
    }
  }

</script>

<style scoped>
  .menu-container {
    display: flex;
    justify-content: space-around;
    height: 100%;
  }

  .my-row {
    flex: 1;
    margin: 10px;
    padding: 5px;
    border-radius: 4px;
    border: 1px solid #dddddd;
    overflow: auto;
  }

  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }

</style>
